package runnable_functions;


import gui.Main;


import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.CountDownLatch;

import javax.xml.parsers.ParserConfigurationException;


import org.xml.sax.SAXException;

import specialfeatures.*;
import details.*;



/**
 * @author Tami
 *
 */
public class SEARCHfunctions extends RunnableClasses{
	

	
	public SEARCHfunctions(){}
	
	public class  GetArtistSearchResults implements Runnable {
		
		private String name;
		private int numOfResults;
		//private ReferedObject searchBy;
		//private ArrayList<Cd> cds;
		//private ArrayList<Song> songs;
		private ArrayList<Artist> artists;
		private CountDownLatch startSignal;
		
		public GetArtistSearchResults(String name ,int numOfResults,CountDownLatch startSignal){
			this.name =name;
			this.numOfResults = numOfResults;
			//this.searchBy = searchBy;
			this.startSignal = startSignal;
		}
		
		
		@Override
		public void run() {

			try {
				Main.db.openConnection();
//				switch(searchBy) {
//				case CD:
//					cds = Main.db.searchByCdTitle(name,SearchType.EXACT, numOfResults);
//					if(cds != null && !cds.isEmpty()){
//						Main.guiInt.updateResultsTableWithCds(cds);
//					}
//					else {
//						Main.guiInt.notifyGeneralError("there is no such cd in db");
//					}
//					break;
//				case SONG:
//					songs = Main.db.searchBySongTitle(name,SearchType.EXACT, numOfResults);
//					if(songs != null && !songs.isEmpty()){
//						Main.guiInt.updateResultsTableWithSongs(songs);
//					}
//					else {
//						Main.guiInt.notifyGeneralError("there is no such song in db");
//					}
//					break;
//					
//				case ARTIST:
				
					artists = Main.db.searchByArtist(name,numOfResults);
					if(artists != null && !artists.isEmpty()){
						Main.guiInt.updateResultsTableWithArtists(artists);
					}
					else {
						Main.guiInt.notifyGeneralError("there is no such artist in db");
					}
					//break;
					
//				case GENRE:
//				
//					cds = Main.db.searchByGenre(name, numOfResults);
//					if(cds != null && !cds.isEmpty()){
//						Main.guiInt.updateResultsTableWithCds(cds);
//					}
//					else {
//						Main.guiInt.notifyGeneralError("there is no cds of such genre in db");
//					}
//					break;
//					
//				case LYRIC:
//					songs = Main.db.searchByLyrics(name,numOfResults);
//					if(songs != null && !songs.isEmpty()){
//						Main.guiInt.updateResultsTableWithSongs(songs);
//					}
//					else {
//						Main.guiInt.notifyGeneralError("there is no such song in db");
//					}
//					break;
//				
//				case YEAR:
//					
//					cds = Main.db.searchCdByYear(Integer.parseInt(name), numOfResults);
//					if(cds != null && !cds.isEmpty()){
//						Main.guiInt.updateResultsTableWithCds(cds);
//					}
//					else {
//						Main.guiInt.notifyGeneralError("there is no cds from such year in db");
//					}
//					break;
//				
//					
//					
//				}
				
				
			} catch (SQLException e) {
				Main.guiInt.notifyDBFailure(e.getMessage());
				
			}
			finally{
			Main.db.closeConnection();
			startSignal.countDown();
			}
			
		}
		
		
	}
	
	
public class  GetAdvancedCdSearchResults implements Runnable {
		//String cdTitle, String performer, String genre, int year, int nomOfResults
		private String titleToSearch;
		private String performerToSearch;
		private String genreToSearch;
		private int yearFrom;
		private int yearTo;
		private int numOfResults;
		private CountDownLatch startSignal;
		
		private ArrayList<Cd> cds;
		
		public GetAdvancedCdSearchResults(String titleToSearch ,String performerToSearch,String genreToSearch,int yearFrom,int yearTo,int numOfResults,CountDownLatch startSignal){
			this.titleToSearch =titleToSearch;
			this.numOfResults = numOfResults;
			this.genreToSearch = genreToSearch;
			this.performerToSearch= performerToSearch;
			this.yearFrom = yearFrom;
			this.yearTo = yearTo;
			this.startSignal = startSignal;
		}
		
		
		@Override
		public void run() {

			try {
				Main.db.openConnection();
				
				cds = Main.db.advanceCDSearch(titleToSearch,performerToSearch,genreToSearch,yearFrom,yearTo,numOfResults);
				if(cds != null && !cds.isEmpty()){
					Main.guiInt.updateResultsTableWithCds(cds);
				}
				else {
					Main.guiInt.notifyGeneralError("there is no such cd in db");
				}
				
					
				
			} catch (SQLException e) {
				Main.guiInt.notifyDBFailure(e.getMessage());
				
			}
			finally{
				Main.db.closeConnection();
				startSignal.countDown();
			}
			
		}
		
		
	}


public class  GetAdvancedSongSearchResults implements Runnable {
	//	public ArrayList<Song> advanceSongSearch(String artistName, String song_title, String words, int nomOfResults) throws SQLException

	private String titleToSearch;
	private String artistToSearch;
	private String wordsToSearch;
	private int numOfResults;
	private CountDownLatch startSignal;
	
	private ArrayList<Song> songs;
	
	public GetAdvancedSongSearchResults(String titleToSearch ,String artistToSearch,String wordsToSearch,int numOfResults,CountDownLatch startSignal){
		this.titleToSearch =titleToSearch;
		this.numOfResults = numOfResults;
		this.wordsToSearch = wordsToSearch;
		this.artistToSearch= artistToSearch;
		this.startSignal = startSignal;
		
	}
	
	
	@Override
	public void run() {

		try {
			Main.db.openConnection();
			
			songs = Main.db.advanceSongSearch(artistToSearch,titleToSearch,wordsToSearch,numOfResults);
			if(songs != null && !songs.isEmpty()){
				Main.guiInt.updateResultsTableWithSongs(songs);
			}
			else {
				Main.guiInt.notifyGeneralError("there is no such song in db");
			}
			
				
			
		} catch (SQLException e) {
			Main.guiInt.notifyDBFailure(e.getMessage());
			
		}
		finally{
			Main.db.closeConnection();
			startSignal.countDown();
		}
		
	}
	
	
}
	

	public class  GetByIdSearchResults implements Runnable {
		
		private String identifier;
		private ReferedObject searchBy;
		
		private Cd cd;
		private Song song;
		private Artist artist;
		private CountDownLatch startSignal;
		
		public GetByIdSearchResults(String identifier,ReferedObject searchBy,CountDownLatch startSignal){
			this.identifier = identifier;
			this.searchBy = searchBy;
			
			this.startSignal = startSignal;
		}
		
		
		@Override
		public void run() {
			
			try {
				Main.db.openConnection();
				switch(searchBy){
				case CD:
					cd = Main.db.searchBy_DISCID(identifier);
					Main.db.addView(identifier, Target.CD);
					Main.guiInt.updateCdInfo(cd);
					ArrayList<Track> cdTracks = cd.getTracks();
					if(cdTracks!=null && !cdTracks.isEmpty()){
					Collections.sort(cdTracks, new Comparator<Object>(){
			            public int compare(Object o1, Object o2) {
			            	Track p1 = (Track) o1;
			            	Track p2 = (Track) o2;
			               return (p1.getTrackNum() - p2.getTrackNum());
			            }
			 
			        });
					
					Main.guiInt.updateCdTracks(cdTracks);
					}
					break;
				case ARTIST:
					//System.out.println("we are in artist case of getIdsearch runnable");
					artist = Main.db.searchByArtistID(Integer.parseInt(identifier));
					if(artist == null){
						Main.guiInt.notifyGeneralError("this artist doesn't have any cds");
						break;
					}
					else{
					//System.out.println("we are after artist retured from dbSearch");
					//System.out.println("the artist details: "+ artist.getName()+" "+ artist.getIdNum());
					//System.out.println("is artist cds array null?"+ (artist.getCds()==null));
					Main.db.addView(identifier, Target.ARTIST);
					Main.guiInt.updateArtistInfo(artist);
					//Main.guiInt.updateArtistCds(artist.getCds());
					//Main.guiInt.notifySuccess()(artist.getCds());
					
					break;
					}
				case SONG:
					song = Main.db.searchBySongID(Integer.parseInt(identifier));
					Main.db.addView(identifier, Target.SONG);
					Main.guiInt.updateSongInfo(song);
					break;
				/* in case of track - the song id is isolated and is the same as in SONG*/
				default:
					break;
				
				}
				
			}
			catch (SQLException e) {
			Main.guiInt.notifyDBFailure(e.getMessage());
			}
			finally{
				Main.db.closeConnection();
				startSignal.countDown();
			}
			
		}
			
	}
	
	
	public class  GetCdCover implements Runnable {
		
		private String performer;
		private String cdTitle;
		private SpecialFeatures cdFeature = new Features();
		private CountDownLatch startSignal;
		
		public GetCdCover(String performer,String cdTitle,CountDownLatch startSignal){
			this.cdTitle=cdTitle;
			this.performer = performer;
			this.startSignal = startSignal;
		}
		@Override
		public void run() {
			try {
				URL  cdCover = cdFeature.getCdCover(performer,cdTitle);
//				if(cdCover==null){
//					//Main.guiInt.notifyGeneralError("the cdCover not found");
//				}
//				else {
					Main.guiInt.updateCdCover(cdCover);
//				}
				
				
			} catch (IOException e) {
				Main.guiInt.notifyGeneralError(e.getMessage());
			} catch (ParserConfigurationException e) {
				Main.guiInt.notifyGeneralError(e.getMessage());
			} catch (SAXException e) {
				Main.guiInt.notifyGeneralError(e.getMessage());
			} catch (InterruptedException e) {
				Main.guiInt.notifyGeneralError(e.getMessage());
			}
			finally{
				startSignal.countDown();
			}
			
			
		}
		
	}
	/* from the lyric db , in case that it is not in our db*/
	public class GetSongLyric implements Runnable{
		
		private Song song;
		private SpecialFeatures cdFeature = new Features();
		private CountDownLatch startSignal;
		
		public GetSongLyric(Song song,CountDownLatch startSignal){
			this.song = song;
			this.startSignal = startSignal;
		}

		@Override
		public void run() {
			String songLyrics = null;
			if(song.getLyric()==null){
				try {
					songLyrics = cdFeature.getLyrics(song.getArtist(), song.getName());
					if (songLyrics==null){
						Main.guiInt.notifyGeneralError("song lyrics not found");
					}
					else {
						Main.db.openConnection();
						Main.db.addLyrics(song.getIdNum(), songLyrics);
						
						Main.guiInt.refreshSongLyric(songLyrics);
					}
					
				} catch (IllegalStateException e) {
					Main.guiInt.notifyGeneralError(e.getMessage());
				} catch (IOException e) {
					Main.guiInt.notifyGeneralError(e.getMessage());
				} catch (ParserConfigurationException e) {
					Main.guiInt.notifyGeneralError(e.getMessage());
				} catch (SAXException e) {
					Main.guiInt.notifyGeneralError(e.getMessage());
				} catch (InterruptedException e) {
					Main.guiInt.notifyGeneralError(e.getMessage());
				} catch (SQLException e) {
					Main.guiInt.notifyDBFailure(e.getMessage());
				}
				finally {
					Main.db.closeConnection();
					startSignal.countDown();
				}
			}
			
		}
		
		
	}
	
	
	
}
